import { Image as ImageLayer, Group } from 'ol/layer';
import Static from 'ol/source/ImageStatic';
import { imageData, geoJSONStyle, WindyData, MarkerOptions, Position } from "../types/MapOptions";  // 导入类型资源
import { MapUtils, MapUtils as Util } from "./MapUtils";

// 图片图层数据处理
export class ImageManager {

  private mapProjectionCode: string = 'EPSG:3857'

  /**  
  * 加载多个图片图层并添加到图层组中
  * @param imageUrl 图片的URL  
  * @param extent 图片的地理范围（经纬度坐标） 
  * @param imageProjection 图片的投影（如果与地图投影不同，则需要进行转换）  
  * @returns 创建的图层  
  */
  public addGroupImageLayer(imageDatas: Array<imageData>): Group {
    const layerGroup = new Group({ layers: [] })
    imageDatas.forEach(imgData => {
      const projection = imgData.imageProjection || this.mapProjectionCode;
      const extent = Util.getMapBounds(imgData.extent) || Util.getMapBounds([-180, -90, 180, 90])
      const imageLayer = new ImageLayer({
        source: new Static({
          url: imgData.imageUrl,
          projection,
          imageExtent: extent  // 默认全球范围
        }),
        opacity: 0.3, // 可根据需要调整不透明度  
        visible: true, // 默认可见  
      });
      layerGroup.getLayers().push(imageLayer)
    })
    return layerGroup;
  }

  /**  
   * 加载单个图片图层并添加到图层组中
   * @param imageUrl 图片的URL  
   * @param extent 图片的地理范围（经纬度坐标） 
   * @param imageProjection 图片的投影（如果与地图投影不同，则需要进行转换）  
   * @returns 创建的图层  
   */
  public addImageLayer(imageData: imageData) {
    const extent = Util.getMapBounds(imageData.extent) || Util.getMapBounds([-180, -90, 180, 90])
    return new ImageLayer({
      zIndex: 2,
      source: new Static({
        url: imageData.imageUrl,
        projection: imageData.imageProjection || this.mapProjectionCode,
        imageExtent: extent  // 默认全球范围
      }),
      opacity: 1, // 可根据需要调整不透明度  
      visible: true, // 默认可见  
    })
  }

}


// 引入必要文件
import { Vector as VectorLayer } from 'ol/layer';
import { Cluster, Vector as VectorSource } from 'ol/source';
import GeoJSON from 'ol/format/GeoJSON';
import * as olStyle from 'ol/style';
// geoJson图层数据处理
export class GeoJSONManager {
  // 批量处理geojson
  public static loadMoreGeoJSON(geojsonData: any, projection: string = "EPSG:3857"): VectorLayer {
    const vectorSource = this.getGeoSource(geojsonData, projection)

    return new VectorLayer({
      source: vectorSource
    })
  }

  // 获取geoJsonVectorSource
  public static getGeoSource(geojsonData: any, projection: string): VectorSource {

    // 使用openlayers 的 geojson 格式解析器将数据转化为 openlayer特征的对象
    const format = new GeoJSON()

    // 创建一个 VectorSource 来存储解析后的特征数据
    const vectorSource = new VectorSource();
    // 遍历要素，设置样式
    geojsonData.forEach((item: { properties: { style: any; }; }) => {
      const features = format.readFeatures(item, {
        featureProjection: projection, // 使用 EPSG:3857 坐标系投影
      });

      features.forEach(feature => {
        const geometryType = feature.getGeometry()?.getType();
        let style;

        // 从 item.properties 获取样式配置
        const styleOptions = item.properties ? item.properties.style : {};

        // 根据几何类型应用不同的样式
        if (geometryType === 'Point') {
          style = this.createStyle('Point', {
            color: styleOptions.color || 'green',  // 默认颜色为绿色
            radius: styleOptions.radius || 4,     // 默认半径为 10
            text: styleOptions.text || ''
          });
        } else if (geometryType === 'LineString') {
          style = this.createStyle('LineString', {
            color: styleOptions.color || 'rgba(0, 0, 255, 0.3)',  // 默认颜色为透明蓝色
            strokeWidth: styleOptions.strokeWidth || 4,              // 默认线宽为 1
            isDashed: styleOptions.isDashed ? [10, 5] : []
          });
        } else if (geometryType === 'Polygon') {
          style = this.createStyle('Polygon', {
            fillColor: styleOptions.fillColor || 'rgba(0, 255, 0, 0.3)',  // 默认填充色为透明绿色
            strokeColor: styleOptions.strokeColor || 'green',            // 默认边框颜色为绿色
            strokeWidth: styleOptions.strokeWidth || 0.5,                // 默认边框宽度为 0.5
          });
        }
        feature.setStyle(style);
      });
      vectorSource.addFeatures(features);
    });
    return vectorSource;
  }


  /** 获取样式
   * 创建点、线、面的样式
   * @param type 几何类型：'Point', 'LineString', 'Polygon'
   * @param options 样式配置选项
   * @returns OpenLayers 样式对象
   */
  public static createStyle(type: string, options: geoJSONStyle) {

    let style;

    switch (type) {
      case 'Point':
        style = new olStyle.Style({
          image: new olStyle.Circle({
            radius: options.radius || 0, // 默认半径 5
            fill: new olStyle.Fill({ color: options.color || 'blue' }),  // 默认填充色为蓝色
            stroke: new olStyle.Stroke({ color: 'black', width: 1 }),  // 黑色边框
          }),
          text: new olStyle.Text({
            text: options.text || '', // 添加文本
            font: '14px Arial', // 设置字体大小和字体类型
            fill: new olStyle.Fill({ color: 'red' }), // 文本填充颜色
            stroke: new olStyle.Stroke({
              color: 'black', // 文本边框颜色
              width: 2        // 边框宽度
            }),
            offsetY: options.radius || 50, // Y轴偏移量，可以根据半径调整
          }),
        });
        break;

      case 'LineString':
        style = new olStyle.Style({
          stroke: new olStyle.Stroke({
            color: options.color || 'red',  // 默认颜色为红色
            width: options.strokeWidth || 1,  // 默认线宽为 1
            lineDash: options.isDashed
          }),
        });
        break;

      case 'Polygon':
        style = new olStyle.Style({
          fill: new olStyle.Fill({
            color: options.fillColor || 'rgba(0, 0, 255, 0.5)',  // 默认填充色为半透明黄色
          }),
          stroke: new olStyle.Stroke({
            color: options.strokeColor || 'rgba(0, 0, 255, 1)',  // 默认边框颜色为黄色
            width: options.strokeWidth || 1,  // 默认边框宽度为 2
          }),
        });
        break;

      default:
        throw new Error(`Unsupported geometry type: ${type}`);
    }

    return style;
  }

  // 将经纬度数组转为GeoJSON格式的点
  public static convertToPoint(lonLat: [number, number]): any {
    const point = new Point(lonLat);
    const feature = new Feature(point);
    const geoJson = new GeoJSON();
    return geoJson.writeFeatureObject(feature);
  }

  // 将经纬度数组转为GeoJSON格式的线
  public static convertToLine(lonLatArray: [number, number][]): any {
    const line = new LineString(lonLatArray);
    const feature = new Feature(line)
    const geoJson = new GeoJSON();
    return geoJson.writeFeatureObject(feature);
  }

  // 将经纬度数组转为GeoJSON格式的面
  public static convertToPolygon(lonLatArray: [number, number][]): any {
    // 如果是封闭的面，需要确保第一个点和最后一个点是相同的
    if (lonLatArray[0] !== lonLatArray[lonLatArray.length - 1]) {
      lonLatArray.push(lonLatArray[0]);
    }

    const polygon = new Polygon([lonLatArray.map(coord => ([coord[0], coord[1]]))]);
    const feature = new Feature(polygon);
    const geoJson = new GeoJSON();
    return geoJson.writeFeatureObject(feature);


  }
}
// 引入必要文件
import shp from "shpjs";
// 文件数据处理
export class FileManager {
  /**
   * 解析CSV数据
   * @param url CSV文件路径
   * @returns 解析后的数据
   */
  public static async analysisCSV(url: string) {
    const response = await fetch(url);
    const arrayBuffer = await response.arrayBuffer();
    const decoder = new TextDecoder('utf-8'); // 指定编码
    const text = decoder.decode(arrayBuffer);
    const filteredLines = text.trim().split(/\r?\n/);
    const lines = filteredLines.slice(1, -1);
    let analysisData: Array<any> = []
    lines.forEach(line => {
      const objLine = line.split(',').map(field => field.trim());
      analysisData.push(objLine)
    });
    return analysisData
  }

  /**
   * 解析shp文件zip
   * @param fileZipPath 解析ZIP   目前用于射界
   * @returns 
   */
  public static async analysisShapefiles(fileZipPath: any) {
    const response = await fetch(fileZipPath);
    const blob = await response.blob();

    const arrayBuffer: unknown = await new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = () => resolve(reader.result);
      reader.onerror = reject;
      reader.readAsArrayBuffer(blob);
    });

    try {
      const buffer = arrayBuffer as string
      const geojson = await shp(buffer);
      return geojson

    } catch (error) {
      console.error('Error loading shapefile:', error);
    }

  }
}


import { Dimensions, fromArrayBuffer } from 'geotiff';
import ImageStatic from "ol/source/ImageStatic";
import { fromLonLat, transformExtent } from "ol/proj";
// 灰度图映射处理
export class GrayToColor {
  private colorMap: Array<any> | undefined
  /*
  * 加载tiff
  * @param url tif文件路径
  * @returns tif文件宽高，像素点
  */
  async loadTiff(url: string, colorMap: Array<any>) {

    this.colorMap = colorMap
    const response = await fetch(url);
    const arrayBuffer = await response.arrayBuffer();
    const tiff = await fromArrayBuffer(arrayBuffer);
    const image = await tiff.getImage();
    const data = await image.readRasters();
    // 重新映射像素
    const mappedData = this.mapPixels(data, image.getWidth(), image.getHeight());
    const boundingBox = image.getBoundingBox();
    return this.mapColor(mappedData, image.getWidth(), image.getHeight(), boundingBox)
  }

  // 像素映射函数
  private mapPixels(pixels: any[] | (Uint8Array & Dimensions) | (Int8Array & Dimensions) | (Uint16Array & Dimensions) | (Int16Array & Dimensions) | (Uint32Array & Dimensions) | (Int32Array & Dimensions) | (Float32Array & Dimensions) | (Float64Array & Dimensions), width: number, height: number) {
    const mappedPixels = new Uint8ClampedArray(width * height * 4); // RGBA
    if (this.colorMap) {
      const numColors = this.colorMap.length;

      pixels.forEach(pixel => {
        for (let i = 0; i < pixel.length; i++) {
          const value = pixel[i];
          let color = [0, 0, 0, 0]; // 默认透明色

          // 根据颜色映射数组查找相应颜色
          for (let j = 0; j < numColors; j++) {
            if (this.colorMap && value <= this.colorMap[j][0]) {
              color = this.colorMap[j][1];
              break;
            }
          }

          // 设置 RGBA 值
          mappedPixels[i * 4] = color[0];      // R
          mappedPixels[i * 4 + 1] = color[1];  // G
          mappedPixels[i * 4 + 2] = color[2];  // B
          mappedPixels[i * 4 + 3] = color[3] * 255; // A (乘以 255)
        }
      });

    }
    return mappedPixels;
  };

  /**
   * 映射到新图层
   * @param mappedData 
   * @param width 
   * @param height 
   * @param boundingBox 
   */
  private mapColor(mappedData: any, width: number, height: number, boundingBox: any) {
    console.log(boundingBox);
    // 创建一个 canvas
    const canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;
    const ctx = canvas.getContext('2d');

    // 将 mappedData 绘制到 canvas 上
    const imageData = new ImageData(mappedData, width, height);
    ctx?.putImageData(imageData, 0, 0);
    const transformedBoundingBox = transformExtent([-180, -80.9, 180, 80.9], 'EPSG:4326', 'EPSG:3857');
    // debugger
    // 将 canvas 转换为 Data URL
    const imageUrl = canvas.toDataURL();

    // 创建静态图层
    const rasterLayer = new ImageLayer({
      source: new ImageStatic({
        url: imageUrl,
        imageExtent: transformedBoundingBox, // 根据数据范围设置
        projection: 'EPSG:3857'
      }),
      zIndex: 2,
      opacity: 0.6
    });
    return rasterLayer
  }

}

// 引入必要的OpenLayers和GeoJSON模块
import Feature from "ol/Feature";
import { Fill, Text, Stroke, Style, Circle, Icon } from "ol/style";

// 行政区划分 / 注记 数据处理
export class GeoJson_bordLine_annotationManager {
  // 边界线基本特征属性
  public static boundar = { Width: 2, Color: "#46aef7", fillColor: "rgba(255,255,255,0.2)" }

  // 注记基本特征属性
  public static annotation = { font: "13px PingFang SC", font_color: "#000", font_bord_color: "#fff", font_bord_width: 2 }


  // 创建一个用于显示边界线的VectorLayer
  public static createBoundaryLayer(geoJsonArray: Array<any>, levelOptions?: { minLevel?: number, maxLevel?: number }): VectorLayer {
    // debugger
    const vectorSource = new VectorSource();
    // 遍历GeoJSON数组，将每个GeoJSON对象转换为Feature并添加到VectorSource中
    geoJsonArray.forEach((geoJson: GeoJSON.GeoJsonObject) => {
      const features = new GeoJSON().readFeatures(geoJson, {
        featureProjection: "EPSG:3857", // 目标投影是WEB Mercator
        dataProjection: "EPSG:4326",  // 源数据投影是WGS 84

      })
      features.forEach((feature: Feature) => {
        feature.setStyle(new Style({
          stroke: new Stroke({
            color: this.boundar.Color, // 边界线颜色
            width: this.boundar.Width   // 边界线宽度
          }),
          fill: new Fill({
            color: this.boundar.fillColor // 填充颜色及透明度
          })
        }))

      })
      vectorSource.addFeatures(features)
    })

    const boundaryLayer = new VectorLayer({
      source: vectorSource,
      zIndex: 3
    })
    if (levelOptions && levelOptions.maxLevel !== undefined) {
      boundaryLayer.setMaxZoom(levelOptions.maxLevel)
    }
    if (levelOptions && levelOptions.minLevel !== undefined) {
      boundaryLayer.setMinZoom(levelOptions.minLevel)
    }
    return boundaryLayer;
  }

  // 创建一个用于显示注记的VerctorLayer
  public static createLabelLayer(geoJsonArray: Array<any>, levelOptions?: { minLevel?: number, maxLevel?: number }): VectorLayer {
    const vectorSource = new VectorSource();
    // 遍历GeoJSON数组，将每个GeoJSON对象转换为Feature并添加到VectorSource中
    geoJsonArray.forEach((geoJson: GeoJSON.GeoJsonObject) => {
      const features = new GeoJSON().readFeatures(geoJson, {
        featureProjection: "EPSG:3857", // 目标投影是WEB Mercator
        dataProjection: "EPSG:4326",  // 源数据投影是WGS 84


      })
      features.forEach((feature: Feature) => {
        const properties = feature.getProperties()
        feature.setStyle(new Style({
          text: new Text({
            font: this.annotation.font,// 注记字体
            text: properties.name, // 根据Feature的属性设置注记内容，假设为name
            fill: new Fill({
              color: this.annotation.font_color // 注记颜色
            }),
            stroke: new Stroke({
              color: this.annotation.font_bord_color,// 注记描边颜色
              width: this.annotation.font_bord_width // 注记描边宽度
            }),
            offsetX: 0 // 注记垂直偏移量，使注记不覆盖在边界线上
          })
        }))
      })
      vectorSource.addFeatures(features)
    })

    const labelLayer = new VectorLayer({
      source: vectorSource,
      zIndex: 3
    })
    if (levelOptions && levelOptions.maxLevel !== undefined) {
      labelLayer.setMaxZoom(levelOptions.maxLevel)
    }
    if (levelOptions && levelOptions.minLevel !== undefined) {
      labelLayer.setMinZoom(levelOptions.minLevel)
    }
    return labelLayer
  }
}

// 导入必要模块
import { WindLayer } from "ol-wind";
import { LineString, Point, Polygon } from 'ol/geom';

// 风场数据处理
export class WindyManager {
  initializationWindLayer(windyData: any, windOptions: WindyData) {
    const defaultWindOptions = {
      colorScale: ["rgb(255, 255, 255)", "rgb(255, 255, 255)", "rgb(255, 255, 255)",
        "rgb(255, 255, 255)", "rgb(255, 255, 255)", "rgb(255, 255, 255)",
        "rgb(255, 255, 255)", "rgb(255, 255, 255)", "rgb(255, 255, 255)",
        "rgb(36, 104, 180)", "rgb(36, 104, 180)", "rgb(36, 104, 180)",
        "rgb(36, 104, 180)", "rgb(36, 104, 180)"],
      globalAlpha: 0.9,   // 粒子透明度
      maxAge: 80,         // 存活最大帧数
      velocityScale: 1 / 30, // 粒子速度
      frameRate: 20,      // 每20帧绘制一次
      paths: 5000,        // 粒子数量
      generateParticleOption: false,
    };

    // 合并用户选项和默认选项
    const finalWindOptions = { ...defaultWindOptions, ...windOptions };

    const windLayer = new WindLayer(windyData, {
      windOptions: finalWindOptions,
    });

    // 设置图层显示优先级
    windLayer.setZIndex(99);
    return windLayer;
  }
}

import { MapBrowserEvent, Map as OlMap } from 'ol';
// 标记点处理
export class OlMarker_Manager {
  private markerSource: VectorSource | undefined;
  private markerLayer: VectorLayer | undefined;
  private markes: Record<string, Feature<Point>> = {};
  private markerPoint = {
    Width: 15,
    Color: "white",
    fillColor: "#000",
    font: "14px Arial",
    backColor: "#ffffffb0",
  };

  // 设置图层样式
  private layerStyle(vectorLayer: VectorLayer) {
    vectorLayer.setStyle((feature) => {
      const properties = feature.getProperties().properties;
      return new Style({
        image: new Icon({
          src: properties.image as string,
          width: properties.id == 'focusing' ? 70 : 40,
        }),
        text: new Text({
          text:
            properties.data.status == 4
              ? properties.name + " | 作业完毕"
              : properties.data.status == 2 ? properties.name + " | 准备就绪" : (properties.name as string),
          fill: new Fill({
            color:
              properties.data.status == 0 ? this.markerPoint.fillColor : "#000",
          }),
          font: this.markerPoint.font,
          // stroke: new Stroke({ color: this.markerPoint.Color, width: this.markerPoint.Width }), //边框色
          offsetY: 30, // 调整文本相对图标垂直位置
          padding: [3, 3, 3, 5],
          textAlign: "center",
          backgroundFill: new Fill({
            color: this.getColor(properties.data.status),
          }),
        }),
      });
    });
  }
  //  添加标记点
  public addMarker(options: MarkerOptions) {
    const { id, name, image, coordinates, data } = options;
    // 创建标记点
    const markerFeatrue = new Feature({
      geometry: new Point(fromLonLat(coordinates)),
      properties: {
        id,
        name,
        image,
        data, // data用于存储额外信息
      },
    });

    // 将标记点添加到图层和记录中
    this.markerSource?.addFeature(markerFeatrue);
    this.markes[id] = markerFeatrue;
  }

  private getColor(state: any) {
    let color = "#FFF";
    switch (state) {
      case 0:
        color = "#FFF";
        break;
      case 1:
        color = "#5299ff";
        break;
      case 2:
        color = "#008000";
        break;
      case 3:
        color = "#550693";
        break;
      case 4:
        color = "#ff0000";
        break;
    }
    return color;
  }
  // 批量添加标记点
  public addMarkers(markers: MarkerOptions[]): VectorLayer {
    this.markerSource = new VectorSource();

    this.markerLayer = new VectorLayer({
      source: this.markerSource,
      zIndex: 4,
    });
    markers.forEach((marker) => this.addMarker(marker));
    // 设置图层样式
    this.layerStyle(this.markerLayer);

    let layer: VectorLayer
    if (markers.length > 100) {
      layer = this.loadPolymerization()
    } else {
      layer = this.markerLayer
    }

    return layer;
  }

  // 删除标记点
  deleteMarker(id: string) {
    const marker = this.markes[id];
    if (marker) {
      this.markerSource?.removeFeature(marker);
      delete this.markes[id];
    }
  }

  // 聚合加载标记点    +++ ***************   （针对数据量大问题）
  // 1.定义真实数据样式  如： 显示文本， 图片 和其他信息 最终生成 每个标记点特征 feature
  // 2.创建聚合源
  // 3.定义聚合样式
  // 4.生成图层
  loadPolymerization() {
    const clusterSource = new Cluster({
      distance: 40,
      source: this.markerSource
    });

    const clusterLayer = new VectorLayer({
      source: clusterSource,
      style: function (feature) {
        const size = feature.get('features').length;

        // 定义通用的文本样式
        const textStyle = new Text({
          text: size.toString(),
          fill: new Fill({ color: 'white' }),
          font: 'bold 14px Arial'
        });

        // 聚合点样式
        const clusterStyle = new Style({
          image: new Circle({
            radius: 10 + size,  // 聚合点的大小
            fill: new Fill({ color: 'rgba(255, 0, 0, 0.6)' }),  // 填充颜色
            stroke: new Stroke({ color: 'white', width: 2 })
          }),
          text: textStyle  // 聚合数量文本
        });

        // 如果聚合点中有单个点，显示该点的图标和文本
        if (size === 1) {
          const singleFeature = feature.get('features')[0]; // 获取单个点
          const properties = singleFeature.get("properties");
          const imageUrl = properties.image; // 获取图片路径

          // 确保 properties.image 和 properties.name 存在
          if (imageUrl && properties.name) {
            const iconStyle = new Style({
              image: new Icon({
                src: imageUrl, // 自定义图标
                scale: 0.2 // 缩放图标
              }),
              text: new Text({
                text: properties.name, // 显示文本
                offsetY: -20,  // 文本偏移
                fill: new Fill({ color: 'black' }),
                font: 'bold 12px Arial'
              })
            });
            return iconStyle; // 返回自定义图标样式
          }
        }

        // 返回聚合点样式
        return clusterStyle;
      }
    });

    clusterLayer.setZIndex(2);
    return clusterLayer;
  }




  //更新标记点
  updateMarkers(newMarkers: MarkerOptions[]) {
    // 清除现有标记点
    this.markerSource?.clear();
    this.markes = {};
    //添加新的标记点
    this.addMarkers(newMarkers);
  }

}

// 鼠标事件处理
export class MouseEventHandler {
  // 绑定鼠标点击事件
  static bindClickEvent(map: OlMap, callback: (coordinate: any) => void): () => void {
    const clickHandler = (event: MapBrowserEvent<MouseEvent>) => {
      callback(event);
    };
    map.on('click', clickHandler);

    // 返回一个清除事件监听的函数
    return () => {
      map.un('click', clickHandler);
    };
  }

  // 绑定鼠标移动事件
  static bindMoveEvent(map: OlMap, callback: (coordinate: number[]) => void): () => void {
    const moveHandler = (event: MapBrowserEvent<MouseEvent>) => {
      const coordinate = event.coordinate;
      callback(coordinate);
    };
    map.on('pointermove', moveHandler);

    // 返回一个清除事件监听的函数
    return () => {
      map.un('pointermove', moveHandler);
    };
  }

  // 绑定缩放事件
  static bindZoomEvent(map: OlMap, callback: (zoom: number) => void): () => void {
    const moveEndHandler = () => {
      const zoom = map.getView().getZoom();
      if (zoom)
        callback(zoom);
    };
    map.on('moveend', moveEndHandler);

    // 返回一个清除事件监听的函数
    return () => {
      map.un('moveend', moveEndHandler);
    };
  }
}

// 集合体处理
export class GeometryManager {
  // 创建呼吸灯效果的高亮圆点
  public static createGlowingPoint(coordinates: [number, number], color: string = 'rgba(255, 0, 0, 1)', minOpacity: number = 0.2, maxOpacity: number = 1, minRadius: number = 5, maxRadius: number = 20, animationSpeed: number = 0.03): VectorLayer {
    let opacity = minOpacity; // 初始透明度
    let radius = minRadius;   // 初始半径
    let increasingOpacity = true;
    let increasingRadius = true;

    // 创建发光点的样式
    const pointStyle: Style = new Style({
      image: new Circle({
        radius: radius,
        fill: new Fill({
          color: `rgba(255, 0, 0, ${opacity})`
        }),
        stroke: new Stroke({
          color: color,
          width: 2
        })
      })
    });

    // 创建点要素
    const pointFeature = new Feature({
      geometry: new Point(coordinates)
    });

    // 创建一个矢量图层
    const vectorLayer = new VectorLayer({
      source: new VectorSource({
        features: [pointFeature]
      }),
      style: pointStyle
    });

    // 动画更新函数
    function animatePoint() {
      // 透明度变化
      if (increasingOpacity) {
        opacity += animationSpeed;
        if (opacity >= maxOpacity) increasingOpacity = false;
      } else {
        opacity -= animationSpeed;
        if (opacity <= minOpacity) increasingOpacity = true;
      }

      // 半径变化
      if (increasingRadius) {
        radius += 0.1;  // 半径平滑增大
        if (radius >= maxRadius) increasingRadius = false;
      } else {
        radius -= 0.1;  // 半径平滑减小
        if (radius <= minRadius) increasingRadius = true;
      }

      // 更新点的样式
      pointStyle.getImage().setFill(new Fill({
        color: `rgba(255, 0, 0, ${opacity})`
      }));
      pointStyle.getImage().setRadius(radius);

      // 继续动画
      requestAnimationFrame(animatePoint);
    }

    // 开始动画
    animatePoint();

    return vectorLayer;
  }


}

export class playBack {
  // 通过线性插值计算当前时间点的模型位置。
  interpolatePosition(
    startTime: number, endTime: number,
    startPosition: Position, endPosition: Position,
    currentTime: number
  ): [number, number] {
    const ratio = (currentTime - startTime) / (endTime - startTime);
    const lat = startPosition.lat + ratio * (endPosition.lat - startPosition.lat);
    const lon = startPosition.lon + ratio * (endPosition.lon - startPosition.lon);
    return [lat, lon];
  }

  // 通过相邻两个点的位置来计算模型的朝向（Heading）。
  calculateHeading(startLat: number, startLon: number, endLat: number, endLon: number): number {
    const deltaLon = endLon - startLon;
    const y = Math.sin(deltaLon) * Math.cos(endLat);
    const x = Math.cos(startLat) * Math.sin(endLat) - Math.sin(startLat) * Math.cos(endLat) * Math.cos(deltaLon);
    const heading = Math.atan2(y, x); // 计算出朝向，单位为弧度
    return heading;
  }

}
